package cn.edu.sjtu.literature.web.controller;

import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;

import au.com.bytecode.opencsv.CSVReader;
import cn.edu.sjtu.literature.entity.Category;
import cn.edu.sjtu.literature.entity.Literature;
import cn.edu.sjtu.literature.service.exception.LiteratureAlreadyExistsException;
import cn.edu.sjtu.literature.web.util.Constants;
import cn.edu.sjtu.literature.web.view.View;

public class LiteratureImportController extends AbstractController {

	protected ServletFileUpload upload;
	
	public LiteratureImportController() {
		DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
		upload = new ServletFileUpload(fileItemFactory);
		upload.setFileSizeMax(4194304);
	}
	
	@Override
	public View doAction(HttpServletRequest req, HttpServletResponse resp) {
		log.debug("do import literatures");
		
		// validate and bind value
		FileItem fileItem = validateAndBind(req);
		if (fileItem == null) {
			log.debug("has field error");
			return getView(Constants.VIEW_LITERATURE_IMPORT);
		}
		
		// export literature
		log.debug("validate field successfully and import literature");
		CSVReader csvReader;
		try {
			csvReader = new CSVReader(new InputStreamReader(fileItem.getInputStream()));
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			req.setAttribute(Constants.ERROR_MESSAGE_KEY, "文献导入失败，请选择正确格式的文件并重试");
			return getView(Constants.VIEW_LITERATURE_IMPORT);
		}
		
		String[] nextLine = null;
		int i = 0;
		try {
			while ((nextLine = csvReader.readNext()) != null) {
				// skip the header
				if (i++ == 0) continue;

				try {
					Literature literature = new Literature();
					literature.setIssueNo(nextLine[1]);
					literature.setTitle(nextLine[2]);
					Category category = new Category();
					category.setId(Integer.parseInt(nextLine[3]));
					category.setName(nextLine[4]);
					literature.setCategory(category);
					literature.setAuthor(nextLine[5]);
					literature.setAuthorFirm(nextLine[6]);
					literature.setAuthorContactInfo(nextLine[7]);
					literature.setSource(nextLine[8]);
					literature.setPublishDate(Constants.NORMAL_DATE_FORMAT.parse(nextLine[9]));
					
					Date now = new Date();
					literature.setCreated(now);
					literature.setCreatedBy(getSessionUser(req).getId());
					literature.setModified(now);
					literature.setModifiedBy(getSessionUser(req).getId());
					
					literatureService.addLiterature(literature);
				} catch (ParseException e) {
					log.warn(e.getMessage(), e);
				} catch (LiteratureAlreadyExistsException e) {
					log.warn(e.getMessage());
				}
			}
		} catch (NumberFormatException e) {
			log.error(e.getMessage(), e);
			req.setAttribute(Constants.ERROR_MESSAGE_KEY, "文献导入失败，请选择正确格式的文件并重试");
			return getView(Constants.VIEW_LITERATURE_IMPORT);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			req.setAttribute(Constants.ERROR_MESSAGE_KEY, "文献导入失败，请选择正确格式的文件并重试");
			return getView(Constants.VIEW_LITERATURE_IMPORT);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			req.setAttribute(Constants.ERROR_MESSAGE_KEY, "文献导入失败，请选择正确格式的文件并重试");
			return getView(Constants.VIEW_LITERATURE_IMPORT);
		}
		
		req.setAttribute(Constants.SUCCESS_MESSAGE_KEY, "文献导入成功");
		return getView(Constants.VIEW_LITERATURE_MESSAGE);
	}

	@SuppressWarnings("unchecked")
	private FileItem validateAndBind(HttpServletRequest req) {
		FileItem result = null;
		
		List<FileItem> fileItems = new ArrayList<FileItem>();
		try {
			fileItems = upload.parseRequest(req);
		} catch (FileUploadException e) {
			log.error(e.getMessage(), e);
			req.setAttribute(getFieldErrorKey("uploadFile"), "上传文件失败");
			return null;
		}
		for (FileItem fileItem : fileItems) {
			if (!fileItem.isFormField()) 
				result = fileItem;
		}
		
		if (result == null) {
			req.setAttribute(getFieldErrorKey("uploadFile"), "请选择文件");
			return null;
		}
		
		log.debug("upload content type: " + result.getContentType());
		log.debug("upload file name: " + result.getName());
		
		if (StringUtils.isBlank(result.getName())) {
			req.setAttribute(getFieldErrorKey("uploadFile"), "请选择文件");
			return null;
		}
		
		if (!StringUtils.containsIgnoreCase(result.getContentType(), "application/csv")) {
			req.setAttribute(getFieldErrorKey("uploadFile"), "文件格式非法");
			return null;
		}
		
		if (!StringUtils.endsWithIgnoreCase(result.getName(), ".csv")) {
			req.setAttribute(getFieldErrorKey("uploadFile"), "文件格式非法");
			return null;
		}
		
		return result;
	}

}
